# -*- coding: utf-8 -*-

# @Author: Chen Hua
# @Date  : 2020-04-11
# @Desc  : 关注的部分指数的基本信息，主要PB,PE信息，
# 本方法只针对 国内的指数，中国香港和国外的另外方法获取

import sys
import datetime
import time
import json

from conf.settings import LXR_TOKEN
from conf.log import log
from db.MySqlConn import DBSession, JobConfig, InvestorAccount, IndexValue
import service.job_config_service as js
from util import DateUtil
import requests

##链接数据库
session = DBSession()
job_name = 'stock_index_info'
###requests对象
s = requests.Session()

"""
获取理杏仁的pbpe数据
https://www.lixinger.com/open/api/detail?api-key=a_stock_fundamental
分点位解释：https://www.lixinger.com/wiki/value-position
"""

##因为理杏仁的有的指数，他又自己定义了一个编码，这个就是映射
# 1000002  沪深A股
# 1000003  深圳A股
# 1000004  上海A股
# 1000007  创业板全指
# 1000011  沪深非金融A股
# 1000012  中小板全指
# 399006  创业板指数

# 000016  上证50指数
# 000903  中证100
# 399330  深证100
# 000300  沪深300
# 000905  中证500
# 000913  沪深300医药

# 399971  中证传媒
# 399986  中证银行
# 399975  全指证券
# 000932  中证主要消费
# 000931  中证可选消费
# 000991  全指医药
# 000993  全指信息技术

# 399967  中证军工
# 000827  中证环保
# 399812  中证养老
# 000015  上证红利
# 000922  中证红利
# H30269  中证红利低波
# H30533  海外中概50指数

# index_codes = ['1000002', '1000003', '1000004', '1000007', '1000011', '1000012', '399006',
#                '000016', '000903', '399330', '000300', '000905', '000913',
#                '399971', '399986', '399975', '000932', '000931', '000991', '000993',
#                '399967', '000827', '399812', '000015', '000922', 'H30269', 'H30533',
#                ]
index_codes_map = {
    '1000002': '沪深A股',
    '1000003': '深圳A股',
    '1000004': '上海A股',
    '1000007': '创业板全指',
    '1000011': '沪深非金融A股',
    '1000012': '中小板全指',
    '399006': '创业板指数',
    '000016': '上证50指数',
    '000903': '中证100',
    '399330': '深证100',
    '000300': '沪深300',
    '000905': '中证500',
    '000913': '沪深300医药',
    '399971': '中证传媒',
    '399986': '中证银行',
    '399975': '全指证券',
    '000932': '中证主要消费',
    '000931': '中证可选消费',
    '000991': '全指医药',
    '000993': '全指信息技术',
    '399967': '中证军工',
    '000827': '中证环保',
    '399812': '中证养老',
    '000015': '上证红利',
    '000922': '中证红利',
    'H30269': '中证红利低波',
    'H30533': '海外中概50指数',
}


def cust_round(value, precision):
    if value is None:
        return 0.0
    return round(value, precision)

def process_lxr_index_api(index_code, begin_dt, end_date):
    for _ in range(2):  # 重试三次
        new_ia_list = []
        try:
            payload = dict(token=LXR_TOKEN,
                           stockCodes=[index_code],
                           startDate=DateUtil.date_to_yyyy_MM_hh_str(begin_dt),
                           endDate=DateUtil.date_to_yyyy_MM_hh_str(end_date),
                           metricsList=["pe_ttm.fs.mcw", "pe_ttm.fs.ew", "pe_ttm.fs.median",
                                        "pe_ttm.fs.ewpvo",
                                        "pb.fs.mcw", "pb.fs.ew", "pb.fs.median", "pb.fs.ewpvo",
                                        "cp","mc","cmc"])
            r = s.post('https://open.lixinger.com/api/a/index/fundamental', data=json.dumps(payload),
                       headers={'Content-Type': 'application/json;charset=UTF-8'})
            rjson = json.loads(r.text)
            # print(rjson)
            result_code = rjson['message']
            # print(result_code)
            if result_code is not None and result_code == 'success':
                rdata = rjson['data']
                if rdata is None:
                    return new_ia_list
                for data in rdata:
                    ##print(data)
                    log.info('获取到 %s %s 的Index value数据..',index_codes_map[index_code], data['date'])
                    dt = DateUtil.yyyy_MM_hh_str_to_date(data['date'][0:10])
                    cp = 0.0
                    if 'cp' in data:
                        cp = round(data['cp'], 3)
                    mc = 0.0
                    if 'mc' in data:
                        mc = round(data['mc'], 3)
                    cmc = 0.0
                    if 'cmc' in data:
                        cmc = round(data['cmc'], 3)
                    pe_ewpvo = {'cv': 0.0, 'cvpos': 0.0}
                    if 'ewpvo' in data['pe_ttm']['fs']:
                        pe_ewpvo = data['pe_ttm']['fs']['ewpvo']
                    pb_ewpvo = {'cv': 0.0, 'cvpos': 0.0}
                    if 'ewpvo' in data['pb']['fs']:
                        pb_ewpvo = data['pb']['fs']['ewpvo']

                    new_ia = IndexValue(index_code=index_code, index_name=index_codes_map[index_code],
                                        pe_ttm_weighted_avg=cust_round(data['pe_ttm']['fs']['mcw']['cv'], 3),
                                        pe_ttm_equal_avg=cust_round(data['pe_ttm']['fs']['ew']['cv'], 3),
                                        pe_ttm_median=cust_round(data['pe_ttm']['fs']['median']['cv'], 3),
                                        pe_ttm_ewpvo=cust_round(pe_ewpvo['cv'], 3),
                                        pb_weighted_avg=cust_round(data['pb']['fs']['mcw']['cv'], 3),
                                        pb_equal_avg=cust_round(data['pb']['fs']['ew']['cv'], 3),
                                        pb_median=cust_round(data['pb']['fs']['median']['cv'], 3),
                                        pb_ewpvo=cust_round(pb_ewpvo['cv'], 3),
                                        dt=dt,
                                        pe_ttm_weighted_val_pos=cust_round(
                                            data['pe_ttm']['fs']['mcw']['cvpos'], 3),
                                        pe_ttm_equal_val_pos=cust_round(data['pe_ttm']['fs']['ew']['cvpos'],
                                                                   3),
                                        pe_ttm_median_val_pos=cust_round(data['pe_ttm']['fs']['median']['cvpos'], 3),
                                        pe_ttm_ewpvo_val_pos=cust_round(pe_ewpvo['cvpos'], 3),
                                        pb_weighted_val_pos=cust_round(data['pb']['fs']['mcw']['cvpos'], 3),
                                        pb_equal_val_pos=cust_round(data['pb']['fs']['ew']['cvpos'], 3),
                                        pb_median_val_pos=cust_round(data['pb']['fs']['median']['cvpos'], 3),
                                        pb_ewpvo_val_pos=cust_round(pb_ewpvo['cvpos'], 3),
                                        cp=cp,
                                        mc=mc,
                                        cmc=cmc
                                        )
                    new_ia_list.append(new_ia)
            else:
                print("没有数据返回，请检查是否出错INDEX_VALUE...")
        except Exception as e:
            print(str(e))
            time.sleep(2)
        else:
            return new_ia_list


def stock_index_info_sync():
    try:
        now = datetime.datetime.now()

        begin_dt = datetime.datetime(1995, 1, 1)  ##默认初始从2004-01-01 开始
        ##从数据库获取上次已获取的数据日期
        spider_config = session.query(JobConfig).filter(JobConfig.job_name == job_name).one()
        if spider_config and spider_config.job_mode == 'inc':
            begin_dt = spider_config.last_data_at
            begin_dt = datetime.datetime(begin_dt.year, begin_dt.month, begin_dt.day)
        # 做时间上的冗余
        end_date = begin_dt + datetime.timedelta(days=5)  # 周一加5天=周五

        while begin_dt < now:
            for index_code in index_codes_map.keys():
                ii_list = process_lxr_index_api(index_code, begin_dt, end_date)
                print("成功爬取指数 ", index_code, begin_dt.date(), "~", end_date.date(), "的信息...")
                for ii in ii_list:
                    session.merge(ii)
                    session.commit()
            js.update_job_config(job_name, begin_dt)
            begin_dt = end_date
            end_date = end_date + datetime.timedelta(days=5)
            time.sleep(3)  # 睡眠3秒
        print('Stock index value info  信息已保存到表 index_value_info ...')
    except Exception as e:
        print('获取Stock index value info 信息失败.')
        print(str(e))
        sys.exit(1)
    finally:
        session.close()


if __name__ == "__main__":
    stock_index_info_sync()
